package Tools;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.security.MessageDigest;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import DAO.LogDAO;

import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;

import javax.crypto.NoSuchPaddingException;
import javax.swing.JOptionPane;

public class Encryptor {

    private String[] iv={	"fds854fds35nfdfs",
							"fdsfds85435nfdfs",
							"854fdsfds35nfdfs",
							"35nffdsfds854dfs",
							"fdsfds85435nfdfs",
							"fdsfdsdfs85435nf",
							"fds85435nffdsdfs",
							"85435nfdfsfdsfds"
						};
    private IvParameterSpec ivspec;
    private SecretKeySpec keyspec;
    private Cipher cipher;

    public Encryptor(String key) 
    {
         try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] secretkey=md.digest(key.getBytes());
            ivspec = new IvParameterSpec(iv[3+2-1].getBytes());
            keyspec = new SecretKeySpec(secretkey, "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            JOptionPane.showMessageDialog(null,"Errore:"+e.getMessage(),"Errore",JOptionPane.ERROR_MESSAGE);
        } catch (NoSuchPaddingException e) {
            JOptionPane.showMessageDialog(null,"Errore:"+e.getMessage(),"Errore",JOptionPane.ERROR_MESSAGE);
        }
    }
    
    public byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                                 + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

   

    public String decrypt(String code) throws Exception {
        if (code == null || code.length() == 0)
            throw new Exception("Empty string");
        byte[] decrypted = null;

        try {
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            decrypted = cipher.doFinal(new Base64().decode(code.getBytes("UTF-8")));
        } catch (Exception e) {
            throw new Exception("[decrypt] " + e.getMessage());
        }
        return new String(decrypted, "UTF-8");
    }

    public static String bytesToHex(byte[] data)
    {
        if (data==null) {
            return null;
        }
        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16) {
                str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
            }
            else {
                str = str + java.lang.Integer.toHexString(data[i]&0xFF);
            }
        }
        return str;
    }

    public static byte[] hexToBytes(String str) {
        if (str==null) {
            return null;
        }
        else if (str.length() < 2) {
            return null;
        }
        else {
            int len = str.length() / 2;
            byte[] buffer = new byte[len];
            for (int i=0; i<len; i++) {
                buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
            }
            return buffer;
        }
    }


    
    public static String getPCCode() throws SocketException{
    	
    	try {
		    InetAddress ip = InetAddress.getLocalHost();
		    //System.out.println("Current IP address : " + ip.getHostAddress());

		    Enumeration<NetworkInterface> networks = NetworkInterface.getNetworkInterfaces();
		    byte[] UniqueMAC= null;
		    while(networks.hasMoreElements()) {
		    	NetworkInterface network = networks.nextElement();
		    	byte[] mac = network.getHardwareAddress();

		    	if(mac != null && mac.length>=6 && Math.abs(mac[0])+Math.abs(mac[1])+Math.abs(mac[2])+Math.abs(mac[3])!=0) {
		    	  
		    		if (UniqueMAC== null){
		    			UniqueMAC=mac;
		    		}else{
		    			String txtMac="";
		    			for (int i = 0; i < mac.length; i++) {
		    				txtMac+=String.format("%02X", mac[i]);
		    			}
		    			String txtUniqueMac="";
		    			for (int i = 0; i < UniqueMAC.length; i++) {
		    				txtUniqueMac+=String.format("%02X", UniqueMAC[i]);
		    			}
		    			if (txtUniqueMac.compareTo(txtMac)<0) {
		    				UniqueMAC=mac;
		    			}
		    		}
		    	}
		        //System.out.print("Current MAC address : ");

		        
		        //System.out.println(sb.toString()+" --> "+SmartCode.encode(mac,true)+" - >"+((mac[0]==0) ? "1":"0"));
		    }
		    String smartCode = SmartCode.encode(UniqueMAC,true);
			return smartCode;
	 
    	} catch (UnknownHostException ex) {
    		return null;
    	}
		
    }

    public static ArrayList<String> getAllCodes() throws SocketException{
    	ArrayList<String> codes=new ArrayList<String>();
    	try {

    		InetAddress ip = InetAddress.getLocalHost();
		    //System.out.println("Current IP address : " + ip.getHostAddress());

		    Enumeration<NetworkInterface> networks = NetworkInterface.getNetworkInterfaces();
		    while(networks.hasMoreElements()) {
		      NetworkInterface network = networks.nextElement();
		      byte[] mac = network.getHardwareAddress();

		      if(mac != null && mac.length>=6 && Math.abs(mac[0])+Math.abs(mac[1])+Math.abs(mac[2])+Math.abs(mac[3])!=0) {
		    	  
		        //System.out.print("Current MAC address : ");

		        String a="";
		        
		        
		        StringBuilder sb = new StringBuilder();
		        for (int i = 0; i < mac.length; i++) {
		        	a+=String.format("%02X", mac[i]);
		        	sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
		        }
		        
		        //System.out.println(sb.toString()+" --> "+a+" "+SmartCode.encode(mac)+" "+SmartCode.encode(mac,true)+" - >"+network.getDisplayName());
		        codes.add(SmartCode.encode(mac,true));
		      	}
		    }
//		    for(String code :codes){
//		        System.out.println(code);		    	
//		    }
			return codes;
	 
    	} catch (UnknownHostException ex) {
    		return null;
    	}
		
    }
    
    
    public static String[] checkLicenza2(int a, int b){
    	File f = new File("license.lic");
    	
		try {
			BufferedReader read=new BufferedReader(new FileReader(f));
			String codice=read.readLine();
			read.close();
			String code=Encryptor.getPCCode();
			Encryptor cipher = new Encryptor(code);
			String response=(a+b)+"%"+cipher.decrypt(codice);
			String[] output=response.split("%");
			if(!output[1].equals(code)) throw new Exception("Licenza invalida per il computer attivo");
			Date dataAccesso=LogDAO.getUltimoAccesso();
			if(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(output [4]).getTime()<dataAccesso.getTime()) throw new Exception("Licenza scaduta");			
			return output;
		} catch (FileNotFoundException e) {
			JOptionPane.showMessageDialog(null,"Verifica della licenza:\nFile license.lic non trovato","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
			return (a+b+2+"%File Licenza Mancante%"+e.getMessage()).split("%");
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null,"Verifica della licenza:\nErrore Lettura file Licenza","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
			return (a+b+3+"%Errore Lettura file Licenza%"+e.getMessage()).split("%");
		} catch (IllegalArgumentException e){
			JOptionPane.showMessageDialog(null,"Verifica della licenza:\nErrore nella verifica della data di scadenza","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
			return (a+b+4+"%Errore data scadenza%"+e.getMessage()).split("%");			
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null,"Verifica della licenza:\n"+e.getMessage(),"Licenza iRor",JOptionPane.WARNING_MESSAGE);			
			return (a+b+5+"%Errore Attivazione Licenza%"+e.getMessage()).split("%");
		}
    }
    
    public static String[] checkLicenza(int a, int b){
    	File f = new File("license.lic");
    	ArrayList<String> codes;
		try {
			codes = Encryptor.getAllCodes();
		} catch (SocketException e1) {
			JOptionPane.showMessageDialog(null,"Verifica della licenza:\nErrore lettura Codice PC","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
			return (a+b+5+"%Errore lettura Codice PC%"+e1.getMessage()).split("%");
		}
    	for (String code:codes){
			try {
				BufferedReader read=new BufferedReader(new FileReader(f));
				String codice=read.readLine();
				read.close();
				
				Encryptor cipher = new Encryptor(code);
				String response=(a+b)+"%"+cipher.decrypt(codice);
				String[] output=response.split("%");
				if(!output[1].equals(code)) continue; //throw new Exception("Licenza invalida per il computer attivo");
				Date dataAccesso=LogDAO.getUltimoAccesso();
				if(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(output [4]).getTime()<dataAccesso.getTime()) throw new Exception("Licenza scaduta");			
				return output;
			} catch (FileNotFoundException e) {
				JOptionPane.showMessageDialog(null,"Verifica della licenza:\nFile license.lic non trovato","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
				return (a+b+2+"%File Licenza Mancante%"+e.getMessage()).split("%");
			} catch (IOException e) {
				JOptionPane.showMessageDialog(null,"Verifica della licenza:\nErrore Lettura file Licenza","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
				return (a+b+3+"%Errore Lettura file Licenza%"+e.getMessage()).split("%");
			} catch (IllegalArgumentException e){
				JOptionPane.showMessageDialog(null,"Verifica della licenza:\nErrore nella verifica della data di scadenza","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
				return (a+b+4+"%Errore data scadenza%"+e.getMessage()).split("%");			
			} catch (Exception e) {
				if (e.getMessage().contains("decrypt")) continue;
				JOptionPane.showMessageDialog(null,"Verifica della licenza:\n"+e.getMessage(),"Licenza iRor",JOptionPane.WARNING_MESSAGE);			
				return (a+b+5+"%Errore Attivazione Licenza%"+e.getMessage()).split("%");
			}
    	}
		JOptionPane.showMessageDialog(null,"Verifica della licenza:\nLicenza non valida","Licenza iRor",JOptionPane.WARNING_MESSAGE);			
		return (a+b+5+"%Errore Attivazione Licenza%\nLicenza non valida").split("%");
    }
    
    
    public static int verifyLicenza(String codice){
		try{
	    	String code=Encryptor.getPCCode();
			Encryptor cipher = new Encryptor(code);
			String response="1"+"%"+cipher.decrypt(codice);
			String[] output=response.split("%");
			if(!output[1].equals(code)) return 2;
			if(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(output [4]).getTime()<LogDAO.getUltimoAccesso().getTime()) return 3;			
			return 1;
		}catch(Exception e){
			return 0;
		}
    }
}